﻿Imports Microsoft.Win32

Public Class OpenVPNConfiguration
    Public Event CreateTunnel(TunnelName As String)
    Public Event SetConfigLine(TunnelName As String, ConfigLine As String)
    Public Event SetDisable(TunnelName As String)
    Public Event ConfigurationNotFoundError()
    Public Event ConfigurationComplete()
    Public Property NoLog As Boolean

    Public Sub ReadConfiguration()
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim TunRoot As RegistryKey = RegRoot.OpenSubKey(Reg_Tunnels_Root)

        ' read config if available
        If IsNothing(TunRoot) Then
            ' no config
            Log("Registry key at [" & Reg_Tunnels_Root & "] not found, can't read configuration.", EventLogEntryType.Error)
            RaiseEvent ConfigurationNotFoundError()
        Else
            Dim TunNames() As String = TunRoot.GetSubKeyNames
            Dim TunCfg As RegistryKey
            Dim TunCfgDirectives() As String
            Dim DirVal As String
            Dim CfgLine As String
            Dim TunDisabled As Boolean = False

            If Not NoLog Then Log("There are [" & TunRoot.SubKeyCount & "] tunnels to configure.", EventLogEntryType.Information)
            For Each TunName As String In TunNames
                ' create new tunnel object
                'NewTun = New Tunnel
                'NewTun.Parent = Me
                'NewTun.Name = TunName
                RaiseEvent CreateTunnel(TunName)
                ' read openvpn configuration for this tunnel from the registry
                TunCfg = TunRoot.OpenSubKey(TunName).OpenSubKey("Configuration")
                TunCfgDirectives = TunCfg.GetValueNames
                ' apply tunnel configuration to openvpn instance (value = directive, data = params)
                For Each Directive As String In TunCfgDirectives
                    Select Case LCase(StripNumber(Directive))
                        Case "disabled"
                            ' marking tunnel as disabled
                            RaiseEvent SetDisable(TunName)
                        Case Else
                            ' setting openvpn.exe configuration
                            DirVal = CStr(TunCfg.GetValue(Directive, ""))
                            ' strip ending numbers from directive names ## ???
                            ' DirVal = StripNumber(DirVal)
                            ' assemble openvpn configuration line
                            CfgLine = Directive & CStr(IIf(DirVal = "", "", " " & DirVal))
                            ' log to win32 event log in verbose mode only
                            'Log("Set tunnel [" & NewTun.Name & "] config [" & CfgLine & "].", EventLogEntryType.Information)
                            ' always log to debug output
                            Dbg("Set tunnel [" & TunName & "] config [" & CfgLine & "].")
                            ' add configuration line to tunnel config
                            RaiseEvent SetConfigLine(TunName, CfgLine)
                    End Select
                Next
            Next
        End If
        RaiseEvent ConfigurationComplete()
    End Sub

    Public Sub ClearTunnelCfg(TunnelName As String)
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim TunRoot As RegistryKey = RegRoot.OpenSubKey(Reg_Tunnels_Root, True)

        ' read config if available
        If IsNothing(TunRoot) Then
            ' no config
            Throw New Exception("Registry key at [" & Reg_Tunnels_Root & "] not found, can't read configuration.")
        Else
            Try
                Dim NewTunKey As RegistryKey = TunRoot.CreateSubKey(TunnelName)
                NewTunKey.DeleteSubKeyTree("Configuration")
                NewTunKey.CreateSubKey("Configuration")
            Catch ex As Exception
                Throw ex
            End Try
        End If
    End Sub

    Public Sub WriteTunnelCfg(TunnelName As String, Setting As String, Optional Value As String = "")
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim TunRoot As RegistryKey = RegRoot.OpenSubKey(Reg_Tunnels_Root)

        ' read config if available
        If IsNothing(TunRoot) Then
            ' no config
            Throw New Exception("Registry key at [" & Reg_Tunnels_Root & "] not found, can't read configuration.")
        Else
            Try
                Dim TunKey As RegistryKey = TunRoot.OpenSubKey(TunnelName)
                Dim CfgKey As RegistryKey = TunKey.OpenSubKey("Configuration", True)
                CfgKey.SetValue(Setting, Value, RegistryValueKind.String)
            Catch ex As Exception
                Throw ex
            End Try
        End If
    End Sub

    Public Sub NewTunnel(TunnelName As String, Optional TunnelEnabled As Boolean = False)
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim TunRoot As RegistryKey = RegRoot.OpenSubKey(Reg_Tunnels_Root, True)

        ' read config if available
        If IsNothing(TunRoot) Then
            ' no config
            Throw New Exception("Registry key at [" & Reg_Tunnels_Root & "] not found, can't read configuration.")
        Else
            Try
                Dim NewTunKey As RegistryKey = TunRoot.CreateSubKey(TunnelName)
                Dim ConfKey As RegistryKey = NewTunKey.CreateSubKey("Configuration")
                NewTunKey.CreateSubKey("Status")
                If Not TunnelEnabled Then ConfKey.SetValue("disabled", "", RegistryValueKind.String)
            Catch ex As Exception
                Throw ex
            End Try
        End If
    End Sub

    Public Sub RemoveTunnel(TunnelName As String)
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim TunRoot As RegistryKey = RegRoot.OpenSubKey(Reg_Tunnels_Root, True)

        ' read config if available
        If IsNothing(TunRoot) Then
            ' no config
            Throw New Exception("Registry key at [" & Reg_Tunnels_Root & "] not found, can't read configuration.")
        Else
            Try
                TunRoot.DeleteSubKeyTree(TunnelName)
            Catch ex As Exception
                Throw ex
            End Try
        End If
    End Sub

    Public Sub WipeConfig()
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim NistonRoot As RegistryKey = RegRoot.OpenSubKey(Reg_NISTON_Root, True)
        NistonRoot.DeleteSubKeyTree("OpenVPNWinSvc")
        NistonRoot = Nothing
    End Sub

    Public Sub InitializeConfig()
        ' obtain HKEY_LOCAL_MACHINE 
        Dim RegRoot As RegistryKey = WinReg.HKEY_LOCAL_MACHINE

        ' obtain tunnel configuration
        Dim NistonRoot As RegistryKey = RegRoot.OpenSubKey(Reg_NISTON_Root, True)
        If NistonRoot Is Nothing Then NistonRoot = RegRoot.CreateSubKey(Reg_NISTON_Root, RegistryKeyPermissionCheck.ReadWriteSubTree)
        Dim SvcRoot As RegistryKey = NistonRoot.OpenSubKey("OpenVPNWinSvc", True)
        If SvcRoot Is Nothing Then SvcRoot = NistonRoot.CreateSubKey("OpenVPNWinSvc", RegistryKeyPermissionCheck.ReadWriteSubTree)
        Dim TunRoot As RegistryKey = SvcRoot.OpenSubKey("Tunnels", True)
        If TunRoot Is Nothing Then TunRoot = SvcRoot.CreateSubKey("Tunnels", RegistryKeyPermissionCheck.ReadWriteSubTree)
        NistonRoot = Nothing
    End Sub

#Region "Helper Functions"
    Function StripNumber(stdText As String) As String
        Dim str As String = "", i As Integer = 0, b As Integer = 1
        'strips the number from a longer text string
        stdText = Trim(stdText)
        For i = Len(stdText) To 1 Step -1
            If IsNumeric(Mid(stdText, i, 1)) Then
                str = Left(stdText, Len(stdText) - b)
                b = b + 1
            Else
                str = stdText
                Exit For
            End If
        Next i
        StripNumber = Trim(str)
    End Function

    Private Sub Log(Message As String, EventType As EventLogEntryType)
        OpenVPNLogging.WLog("OpenVPNConfiguration: " & Message, EventType)
    End Sub
    Private Sub Dbg(Message As String)
        OpenVPNLogging.WDbg("OpenVPNConfiguration: " & Message)
    End Sub

#End Region



End Class
